home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / SNNSV32.ZIP / SNNSv3.2 / kernel / sources / cc_learn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-25  |  49.2 KB  |  1,633 lines

  1. /*****************************************************************************
  2.   FILE           : cc_learn.c
  3.   SHORTNAME      : 
  4.   SNNS VERSION   : 3.2
  5.  
  6.   PURPOSE        : Functions of CC
  7.   NOTES          :
  8.  
  9.   AUTHOR         : Michael Schmalzl
  10.   DATE           : 5.2.93
  11.  
  12.   CHANGED BY     : Michael Schmalzl
  13.   IDENTIFICATION : @(#)cc_learn.c    1.13 4/7/94
  14.   SCCS VERSION   : 1.13
  15.   LAST CHANGE    : 4/7/94
  16.  
  17.              Copyright (c) 1990-1994  SNNS Group, IPVR, Univ. Stuttgart, FRG
  18.  
  19. ******************************************************************************/
  20.  
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include <time.h>  
  24. #include <memory.h>
  25. #include <malloc.h>
  26. #include <values.h>
  27.  
  28. #include "kr_typ.h"      /*  Kernel Types and Constants  */
  29. #include "kr_const.h"    /*  Constant Declarators for SNNS-Kernel  */
  30. #include "kr_def.h"      /*  Default Values  */
  31. #include "kernel.h"      /*  kernel function prototypes  */
  32. #include "kr_mac.h"      /*  Kernel Macros   */
  33.  
  34. #include "kr_ui.h"
  35.  
  36. #include "cc_type.h"
  37. #include "cc_mac.h"
  38. #include "cc_learn.ph"
  39. #include "cc_rcc.h"
  40. #include "kr_newpattern.h"
  41.  
  42.  
  43. /*****************************************************************************
  44.   FUNCTION : cc_propagateNetForward
  45.  
  46.   PURPOSE  : Propagates a pattern forward through the net 
  47.   NOTES    :
  48.  
  49.   UPDATE   : 5.2.93
  50. ******************************************************************************/
  51. static void cc_propagateNetForward(int PatternNo, int sub_pat_no)
  52. {
  53.     register struct Unit  *inputUnitPtr,*outputUnitPtr,*hiddenUnitPtr;
  54.     register Patterns  in_pat;
  55.     register int dummy;
  56.  
  57.     in_pat = kr_getSubPatData(PatternNo,sub_pat_no,INPUT,NULL);
  58.  
  59.     FOR_ALL_INPUT_UNITS(inputUnitPtr,dummy){
  60.     if(inputUnitPtr->out_func == OUT_IDENTITY) {
  61.         inputUnitPtr->Out.output = inputUnitPtr->act = *in_pat++;
  62.     }else{
  63.         inputUnitPtr->Out.output = 
  64.         (*inputUnitPtr->out_func) (inputUnitPtr->act = *in_pat++);
  65.     }
  66.     }
  67.  
  68.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,dummy) {
  69.     hiddenUnitPtr->act = (*hiddenUnitPtr->act_func)(hiddenUnitPtr);
  70.     if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  71.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  72.     }else{
  73.         hiddenUnitPtr->Out.output = 
  74.         (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  75.     }
  76.     }
  77.  
  78.     FOR_ALL_OUTPUT_UNITS(outputUnitPtr,dummy) {
  79.     outputUnitPtr->act = (*outputUnitPtr->act_func) (outputUnitPtr);
  80.     if(outputUnitPtr->out_func == OUT_IDENTITY) {
  81.         outputUnitPtr->Out.output = outputUnitPtr->act;
  82.     }else{
  83.         outputUnitPtr->Out.output = 
  84.         (*outputUnitPtr->out_func) (outputUnitPtr->act);
  85.     }
  86.     }
  87. }
  88.  
  89.  
  90.  
  91. /*****************************************************************************
  92.   FUNCTION : cc_calculateOutputUnitError
  93.  
  94.   PURPOSE  : Calculates the error of all output units and stores the result
  95.              in the array OutputUnitError
  96.   NOTES    :
  97.  
  98.   UPDATE   : 5.2.93
  99. ******************************************************************************/
  100. static void cc_calculateOutputUnitError(int StartPattern,int EndPattern)
  101. {
  102.     register struct Unit  *inputUnitPtr,*outputUnitPtr,*hiddenUnitPtr;
  103.     register Patterns  in_pat,out_pat;
  104.     register TopoPtrArray     topo_ptr;
  105.     register int dummy,o,p;
  106.     int start, end;
  107.     int pat, sub;
  108.   
  109.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  110.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  111.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  112.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  113.     for(p=start; p<=end;p++){
  114.  
  115.     topo_ptr = topo_ptr_array;
  116.     kr_getSubPatternByNo(&pat,&sub,p);
  117.     in_pat = kr_getSubPatData(pat,sub,INPUT,NULL);
  118.     out_pat = kr_getSubPatData(pat,sub,OUTPUT,NULL);
  119.  
  120.     FOR_ALL_INPUT_UNITS(inputUnitPtr,dummy){
  121.         if(inputUnitPtr->out_func == OUT_IDENTITY) {
  122.         inputUnitPtr->Out.output = inputUnitPtr->act = *in_pat++;
  123.         }else{
  124.         inputUnitPtr->Out.output = 
  125.             (*inputUnitPtr->out_func) (inputUnitPtr->act = *in_pat++);
  126.         }
  127.     }
  128.  
  129.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,dummy) {
  130.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func) (hiddenUnitPtr);
  131.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  132.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  133.         }else{
  134.         hiddenUnitPtr->Out.output = 
  135.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  136.         }
  137.     }
  138.     
  139.     FOR_ALL_OUTPUT_UNITS(outputUnitPtr,o) {
  140.         outputUnitPtr->act = (*outputUnitPtr->act_func)(outputUnitPtr);
  141.         if(outputUnitPtr->out_func == OUT_IDENTITY) {
  142.         outputUnitPtr->Out.output = outputUnitPtr->act;
  143.         }else{
  144.         outputUnitPtr->Out.output = 
  145.             (*outputUnitPtr->out_func) (outputUnitPtr->act);
  146.         }
  147.         OutputUnitSumError[o] += 
  148.         (OutputUnitError[p][o] =  
  149.               (outputUnitPtr->Out.output-(*out_pat++))*
  150.               ((*outputUnitPtr->act_deriv_func)(outputUnitPtr)+0.1)); 
  151.     }
  152.     }
  153. }
  154.  
  155.  
  156.  
  157. /*****************************************************************************
  158.   FUNCTION :  cc_calculateSpecialUnitActivation
  159.  
  160.   PURPOSE  :  Calculates the covariance  between the output units and the 
  161.               special units and stores the result the array 
  162.           CorBetweenSpecialActAndOutError.
  163.   NOTES    :
  164.  
  165.   UPDATE   : 5.2.93
  166. ******************************************************************************/
  167. static void cc_calculateSpecialUnitActivation(int StartPattern, int EndPattern)
  168. {
  169.     register struct Unit  *inputUnitPtr,*specialUnitPtr,
  170.                           *outputUnitPtr,*hiddenUnitPtr;
  171.     register Patterns  in_pat,out_pat;
  172.     register int dummy,o,s,p;
  173.     int pat,sub;
  174.     int start,end;
  175.   
  176.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  177.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  178.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  179.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  180.     for(p=start; p<=end;p++){
  181.  
  182.     kr_getSubPatternByNo(&pat,&sub,p);
  183.     in_pat = kr_getSubPatData(pat,sub,INPUT,NULL);
  184.  
  185.     FOR_ALL_INPUT_UNITS(inputUnitPtr,dummy){
  186.         if(inputUnitPtr->out_func == OUT_IDENTITY) {
  187.         inputUnitPtr->Out.output = inputUnitPtr->act = *in_pat++;
  188.         }else{
  189.         inputUnitPtr->Out.output = 
  190.             (*inputUnitPtr->out_func) (inputUnitPtr->act = *in_pat++);
  191.         }
  192.     }
  193.  
  194.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,dummy) {
  195.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func) (hiddenUnitPtr);
  196.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  197.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  198.         }else{
  199.         hiddenUnitPtr->Out.output = 
  200.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  201.         }
  202.     }
  203.     
  204.     FOR_ALL_SPECIAL_UNITS(specialUnitPtr,s) {
  205.         specialUnitPtr->act = (*specialUnitPtr->act_func) (specialUnitPtr);
  206.         if(specialUnitPtr->out_func == OUT_IDENTITY) {
  207.         specialUnitPtr->Out.output = specialUnitPtr->act;
  208.         }else{
  209.         specialUnitPtr->Out.output = 
  210.             (*specialUnitPtr->out_func) (specialUnitPtr->act);
  211.         }
  212.         SpecialUnitSumAct[s] += 
  213.         SpecialUnitAct[p][s] = specialUnitPtr->Out.output;
  214.     }
  215.     } 
  216.  
  217.     for(p=start; p<=end;p++){
  218.     FOR_ALL_SPECIAL_UNITS(specialUnitPtr,s) {
  219.         FOR_ALL_OUTPUT_UNITS(outputUnitPtr,o) {
  220.         CorBetweenSpecialActAndOutError[s][o] += 
  221.             SpecialUnitAct[p][s] * OutputUnitError[p][o];
  222.         }
  223.     }
  224.     }    
  225. }
  226.  
  227.  
  228.  
  229. /************* begin backprop routines *********************/
  230.  
  231. /*****************************************************************************
  232.   FUNCTION : cc_BPO_trainNet
  233.  
  234.   PURPOSE  : Trains the output units with backprop.
  235.   NOTES    :
  236.  
  237.   UPDATE   : 5.2.93
  238. ******************************************************************************/
  239. static void cc_BPO_trainNet(int maxNoOfErrorUpdateCycles, float minErrorChange,
  240.                             int outPatience,int StartPattern,int EndPattern, 
  241.                 float eta, float mu, float fse, 
  242.                 float **ParameterOutArray,int *NoOfOutParams)
  243. {
  244.     int m,p,pat,sub,counter=0;
  245.     float oldNetError;
  246.     static float OutParameter[1];
  247.     int start,end;
  248.  
  249.     *NoOfOutParams = 1;
  250.     *ParameterOutArray = OutParameter;
  251.  
  252.     SumSqError = 0.0;
  253.     cc_initOutputUnits();
  254.  
  255.     /* compute the necessary sub patterns */
  256.  
  257.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  258.     if(KernelErrorCode != KRERR_NO_ERROR)
  259.         return;
  260.  
  261.     /* give oldNetError a meaningful initial value */
  262.  
  263.     NET_ERROR(OutParameter)=FLOAT_MAX;
  264.     do {
  265.     oldNetError = NET_ERROR(OutParameter);
  266.     for(m=0;m<outPatience;m++) {
  267.         NET_ERROR(OutParameter) = 0.0;
  268.         SumSqError = 0.0;
  269.  
  270.         KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  271.         start = kr_AbsPosOfFirstSubPat(StartPattern);
  272.         end   = kr_AbsPosOfFirstSubPat(EndPattern);
  273.         end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  274.         for(p=start; p<=end;p++){
  275.         kr_getSubPatternByNo(&pat,&sub,p);
  276.         cc_propagateNetForward(pat,sub);
  277.         NET_ERROR(OutParameter) += 
  278.             cc_BPO_propagateNetBackward(pat,sub,eta,mu,fse);
  279.         }
  280.         if(cc_printOnOff){
  281.         printf("Epoch: %d NetError: %f \n",++counter,
  282.                NET_ERROR(OutParameter));
  283.         }
  284.         if((maxNoOfErrorUpdateCycles--) == 0) {
  285.         return;
  286.         }
  287.     }
  288.     } while(fabs(oldNetError-NET_ERROR(OutParameter)) >= 
  289.         (minErrorChange*oldNetError));
  290. }
  291.  
  292.  
  293.  
  294. /*****************************************************************************
  295.   FUNCTION : cc_BPO_propagateNetBackward
  296.  
  297.   PURPOSE  : Calculates the error of the net with backprop.
  298.   NOTES    :
  299.  
  300.   UPDATE   : 5.2.93
  301. ******************************************************************************/
  302. static  float cc_BPO_propagateNetBackward(int PatternNo, int sub_pat_no,
  303.                       float eta, float mu, float fse)
  304. {
  305.     struct Link   *LinkPtr;
  306.     struct Site   *site_ptr;
  307.     struct Unit   *OutputUnitPtr;
  308.     Patterns      out_pat;
  309.     float         error,sum_error,devit,bias_previousSlope,ln_previousSlope;
  310.     int           dummy;
  311.  
  312.     sum_error = 0.0;    
  313.     out_pat = kr_getSubPatData(PatternNo,sub_pat_no,OUTPUT,NULL);
  314.  
  315.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
  316.     devit =  OutputUnitPtr->Out.output - *(out_pat++);
  317.  
  318.     sum_error += devit * devit;
  319.     error = devit * ((*OutputUnitPtr->act_deriv_func)(OutputUnitPtr) + fse);
  320.     SumSqError += error * error;
  321.  
  322.     bias_previousSlope = BIAS_PREVIOUS_SLOPE(OutputUnitPtr);
  323.     OutputUnitPtr->bias -= 
  324.         ((BIAS_PREVIOUS_SLOPE(OutputUnitPtr) = 
  325.             error * eta  + bias_previousSlope * mu));
  326.  
  327.     if (UNIT_HAS_DIRECT_INPUTS(OutputUnitPtr)) { 
  328.         FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  329.         ln_previousSlope =  LN_PREVIOUS_SLOPE(LinkPtr);
  330.         LinkPtr->weight -= 
  331.             ((LN_PREVIOUS_SLOPE(LinkPtr) = 
  332.                 error*LinkPtr->to->Out.output*eta+ln_previousSlope*mu));
  333.         }
  334.     }
  335.     else {
  336.         FOR_ALL_SITES_AND_LINKS(OutputUnitPtr,site_ptr,LinkPtr) {
  337.         ln_previousSlope =  LN_PREVIOUS_SLOPE(LinkPtr);
  338.         LinkPtr->weight -= 
  339.             ((LN_PREVIOUS_SLOPE(LinkPtr) = 
  340.               error*LinkPtr->to->Out.output*eta+ln_previousSlope*mu));
  341.         }
  342.     }
  343.     }
  344.     return(sum_error); 
  345. }
  346.  
  347.  
  348.  
  349. /*****************************************************************************
  350.   FUNCTION : cc_BPS_trainNet
  351.  
  352.   PURPOSE  : Trains the special units with backprop.
  353.   NOTES    :
  354.  
  355.   UPDATE   : 5.2.93
  356. ******************************************************************************/
  357. static void cc_BPS_trainNet(int maxNoOfCovarianceUpdateCycles, 
  358.                 float minCovarianceChange,
  359.                             int specialPatience,int StartPattern, 
  360.                 int EndPattern, float eta, float mu, float dummy1, 
  361.                 int MaxSpecialUnitNo)
  362. {
  363.     int m,counter=0;
  364.     float oldHighScore,newHighScore=0.0;
  365.  
  366.     cc_initErrorArrays();
  367.     cc_calculateOutputUnitError(StartPattern,EndPattern);
  368.  
  369.     do {
  370.     oldHighScore = newHighScore;
  371.     for(m=0;m<specialPatience;m++) { 
  372.         counter++;
  373.         cc_calculateSpecialUnitActivation(StartPattern,EndPattern);
  374.         newHighScore = cc_BPS_propagateNetBackward(StartPattern,EndPattern,
  375.                                counter,eta,mu);
  376.         cc_initActivationArrays(); 
  377.         if((maxNoOfCovarianceUpdateCycles--) == 0) {
  378.         return;
  379.         }
  380.     }
  381.     } while(fabs(newHighScore-oldHighScore) >= 
  382.         (minCovarianceChange * oldHighScore));
  383. }
  384.  
  385.  
  386.  
  387. /*****************************************************************************
  388.   FUNCTION : cc_BPS_propagateNetBackward
  389.  
  390.   PURPOSE  : Calculates the covariance of the special units and returns
  391.              the best unit.
  392.   NOTES    :
  393.  
  394.   UPDATE   : 5.2.93
  395. ******************************************************************************/
  396. static float cc_BPS_propagateNetBackward(int StartPattern, int EndPattern, 
  397.                      int counter, float eta, float mu)
  398. {
  399.     float change=0.0,bestSpecialUnitScore;
  400.     int s,o,p,n,h;
  401.     struct Unit *SpecialUnitPtr,*OutputUnitPtr,*hiddenUnitPtr;
  402.     struct Link *LinkPtr;
  403.     float ln_previousSlope,bias_previousSlope,actPrime;
  404.     int start,end;
  405.  
  406.     bestSpecialUnitScore = 
  407.     cc_calculateCorrelation(StartPattern,EndPattern,counter); 
  408.  
  409.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  410.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  411.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  412.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  413.     n = end - start +1;
  414.     for(p=start; p<=end;p++){
  415.  
  416.     cc_initInputUnitsWithPattern(p);
  417.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,h) {
  418.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func) (hiddenUnitPtr);
  419.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  420.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  421.         }else{
  422.         hiddenUnitPtr->Out.output = 
  423.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  424.         }
  425.     }
  426.     
  427.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s) {
  428.         change = 0.0;
  429.         SpecialUnitPtr->act = SpecialUnitAct[p][s];
  430.         actPrime = (*SpecialUnitPtr->act_deriv_func)(SpecialUnitPtr);
  431.         FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  432.         change += CorBetweenSpecialActAndOutError[s][o] * actPrime *  
  433.            ((OutputUnitError[p][o]-OutputUnitSumError[o]/n)/SumSqError);
  434.         }
  435.         bias_previousSlope = BIAS_PREVIOUS_SLOPE(SpecialUnitPtr);
  436.         SpecialUnitPtr->bias += 
  437.         (BIAS_PREVIOUS_SLOPE(SpecialUnitPtr) = 
  438.          (change * eta + bias_previousSlope * mu));     
  439.         FOR_ALL_LINKS(SpecialUnitPtr,LinkPtr) {
  440.         ln_previousSlope = LN_PREVIOUS_SLOPE(LinkPtr);
  441.         LinkPtr->weight += 
  442.             (LN_PREVIOUS_SLOPE(LinkPtr) = 
  443.              change*LinkPtr->to->Out.output*eta+ln_previousSlope*mu);
  444.         }
  445.     }
  446.     }
  447.     return(bestSpecialUnitScore);
  448. }
  449.  
  450.  
  451. /******************* end backprop routines *************************/
  452.  
  453.  
  454. /************* begin quickprop routines *********************/
  455.  
  456. /*****************************************************************************
  457.   FUNCTION : cc_QPO_trainNet
  458.  
  459.   PURPOSE  : Trains the output units with quickprop.
  460.   NOTES    :
  461.  
  462.   UPDATE   : 5.2.93
  463. ******************************************************************************/
  464. static void cc_QPO_trainNet(int maxNoOfErrorUpdateCycles, float minErrorChange,
  465.                 int outPatience, int StartPattern, int EndPattern, 
  466.                 float epsilon, float mu, float decay, 
  467.                 float **ParameterOutArray, int *NoOfOutParams)
  468. {
  469.     int m,p,sub,pat,counter=0;
  470.     float oldNetError;
  471.     static float OutParameter[1];
  472.     int start, end;
  473.  
  474.     *NoOfOutParams = 1;
  475.     *ParameterOutArray = OutParameter;
  476.  
  477.     SumSqError = 0.0;
  478.     cc_initOutputUnits();
  479.  
  480.     /* compute the necessary sub patterns */
  481.  
  482.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  483.     if(KernelErrorCode != KRERR_NO_ERROR)
  484.         return;
  485.  
  486.     /* give oldNetError a meaningful initial value */
  487.  
  488.     NET_ERROR(OutParameter)=FLOAT_MAX;
  489.     do {
  490.     oldNetError = NET_ERROR(OutParameter);
  491.     for(m=0;m<outPatience;m++) {
  492.         NET_ERROR(OutParameter) = 0.0;
  493.         SumSqError = 0.0;
  494.         KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  495.         start = kr_AbsPosOfFirstSubPat(StartPattern);
  496.         end   = kr_AbsPosOfFirstSubPat(EndPattern);
  497.         end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  498.         for(p=start; p<=end;p++){
  499.         kr_getSubPatternByNo(&pat,&sub,p);
  500.         cc_propagateNetForward(pat,sub);
  501.         NET_ERROR(OutParameter) += cc_QPO_propagateNetBackward(pat,sub);
  502.         }
  503.         cc_QPO_updateNet(epsilon,mu,decay);
  504.         if(cc_printOnOff) {
  505.         printf("Epoch: %d NetError: %f \n",++counter,
  506.                NET_ERROR(OutParameter));
  507.         }
  508.         if((maxNoOfErrorUpdateCycles--) == 0) {
  509.         return;
  510.         }
  511.     }
  512.     } while(fabs(oldNetError-NET_ERROR(OutParameter)) >= 
  513.         (minErrorChange * oldNetError));
  514. }
  515.  
  516.  
  517.  
  518. /*****************************************************************************
  519.   FUNCTION : cc_QPO_propagateNetBackward
  520.  
  521.   PURPOSE  : Propagates a pattern backward through the net.
  522.   NOTES    :
  523.  
  524.   UPDATE   : 5.2.93
  525. ******************************************************************************/
  526. static  float cc_QPO_propagateNetBackward(int PatternNo, int sub_pat_no)
  527. {
  528.     struct Link   *LinkPtr;
  529.     struct Site   *site_ptr;
  530.     struct Unit   *OutputUnitPtr;
  531.     Patterns      out_pat;
  532.     float         error,sum_error,devit;
  533.     int           dummy;
  534.  
  535.     sum_error = 0.0;    
  536.     out_pat = kr_getSubPatData(PatternNo,sub_pat_no,OUTPUT,NULL);
  537.  
  538.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
  539.     devit =  OutputUnitPtr->Out.output - *(out_pat++);
  540.  
  541.     sum_error += devit * devit;
  542.     error = devit * ((*OutputUnitPtr->act_deriv_func)(OutputUnitPtr) + 0.1);
  543.     SumSqError += error * error;
  544.  
  545.     BIAS_CURRENT_SLOPE(OutputUnitPtr) += error;
  546.  
  547.     if (UNIT_HAS_DIRECT_INPUTS(OutputUnitPtr)) {  
  548.         FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  549.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  550.         }
  551.     }else{
  552.         FOR_ALL_SITES_AND_LINKS(OutputUnitPtr,site_ptr,LinkPtr) {
  553.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  554.         }
  555.     }
  556.     }
  557.     return(sum_error); 
  558. }
  559.  
  560.  
  561.  
  562. /*****************************************************************************
  563.   FUNCTION : cc_QPO_updateNet
  564.  
  565.   PURPOSE  : Updates the output weights of a net using quickprop.
  566.   NOTES    :
  567.  
  568.   UPDATE   : 5.2.93
  569. ******************************************************************************/
  570. static void cc_QPO_updateNet(float epsilon, float mu, float decay)
  571. {
  572.     struct Unit *OutputUnitPtr;
  573.     struct Link *LinkPtr;
  574.     float shrinkFactor = mu/(mu+1);
  575.     float bias_previousSlope,bias_currentSlope,bias_lastWeightChange,
  576.           bias_weightChange;
  577.     float ln_previousSlope,ln_currentSlope,ln_lastWeightChange,ln_weightChange;
  578.     int o;
  579.  
  580.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  581.     bias_previousSlope = BIAS_PREVIOUS_SLOPE(OutputUnitPtr);
  582.     bias_currentSlope = 
  583.         BIAS_CURRENT_SLOPE(OutputUnitPtr) + decay * OutputUnitPtr->bias;
  584.     bias_lastWeightChange = BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr);
  585.  
  586.     bias_weightChange = 0.0;
  587.  
  588.     if(bias_previousSlope > 0.0) {
  589.         if(bias_currentSlope > 0.0) {
  590.         bias_weightChange -= epsilon * bias_currentSlope;
  591.         }
  592.         if(bias_currentSlope >= (shrinkFactor * bias_previousSlope)) {
  593.         bias_weightChange += mu * bias_lastWeightChange;
  594.         }else{
  595.         bias_weightChange += (bias_lastWeightChange*bias_currentSlope)/ 
  596.             (bias_previousSlope - bias_currentSlope); 
  597.         }
  598.     }else if(bias_previousSlope < 0.0) {
  599.         if(bias_currentSlope < 0.0) {
  600.         bias_weightChange -= epsilon * bias_currentSlope;
  601.         }
  602.         if(bias_currentSlope <= (shrinkFactor * bias_previousSlope)) {
  603.         bias_weightChange += mu * bias_lastWeightChange;
  604.         }else{
  605.         bias_weightChange += (bias_lastWeightChange*bias_currentSlope)/ 
  606.             (bias_previousSlope - bias_currentSlope); 
  607.         }
  608.     }else{
  609.         bias_weightChange -= epsilon * bias_currentSlope;
  610.     }
  611.     OutputUnitPtr->bias += 
  612.         (BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr) = bias_weightChange); 
  613.     BIAS_PREVIOUS_SLOPE(OutputUnitPtr) = bias_currentSlope;
  614.     BIAS_CURRENT_SLOPE(OutputUnitPtr) = 0.0;
  615.  
  616.     FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  617.    
  618.         ln_weightChange = 0.0;
  619.         ln_previousSlope = LN_PREVIOUS_SLOPE(LinkPtr);
  620.         ln_currentSlope = LN_CURRENT_SLOPE(LinkPtr) + decay*LinkPtr->weight;
  621.         ln_lastWeightChange = LN_LAST_WEIGHT_CHANGE(LinkPtr);
  622.    
  623.         if(ln_previousSlope > 0.0) {
  624.         if(ln_currentSlope > 0.0) {
  625.             ln_weightChange -= epsilon * ln_currentSlope;
  626.         }
  627.         if(ln_currentSlope >= (shrinkFactor * ln_previousSlope)) {
  628.             ln_weightChange += mu * ln_lastWeightChange;
  629.         }else{
  630.             ln_weightChange += (ln_lastWeightChange*ln_currentSlope) / 
  631.             (ln_previousSlope - ln_currentSlope); 
  632.         }
  633.         }else if(ln_previousSlope < 0.0) {
  634.         if(ln_currentSlope < 0.0) {
  635.             ln_weightChange -= epsilon * ln_currentSlope;
  636.         }
  637.         if(ln_currentSlope <= (shrinkFactor * ln_previousSlope)) {
  638.             ln_weightChange += mu * ln_lastWeightChange;
  639.         }else {
  640.             ln_weightChange += (ln_lastWeightChange*ln_currentSlope) / 
  641.             (ln_previousSlope - ln_currentSlope); 
  642.         }
  643.         }else{
  644.         ln_weightChange -= epsilon * ln_currentSlope;
  645.         }
  646.    
  647.         LinkPtr->weight += LN_LAST_WEIGHT_CHANGE(LinkPtr) = ln_weightChange;
  648.         LN_PREVIOUS_SLOPE(LinkPtr)   = ln_currentSlope;
  649.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  650.     }
  651.     }
  652. }
  653.  
  654.  
  655.  
  656. /*****************************************************************************
  657.   FUNCTION : cc_QPS_trainNet
  658.  
  659.   PURPOSE  : Maximize the covariance of the special units.
  660.   NOTES    :
  661.  
  662.   UPDATE   : 5.2.93
  663. ******************************************************************************/
  664. static void cc_QPS_trainNet(int maxNoOfCovarianceUpdateCycles, 
  665.                 float minCovarianceChange, int specialPatience, 
  666.                 int StartPattern, int EndPattern, 
  667.                 float epsilon, float mu, float decay, 
  668.                 int MaxSpecialUnitNo)
  669. {
  670.     int m,counter=0;
  671.     float oldHighScore,newHighScore=0.0;
  672.  
  673.     cc_initErrorArrays();
  674.     cc_calculateOutputUnitError(StartPattern,EndPattern);
  675.  
  676.     do {
  677.     oldHighScore = newHighScore;
  678.     for(m=0;m<specialPatience;m++) { 
  679.         counter++;
  680.         cc_calculateSpecialUnitActivation(StartPattern,EndPattern);
  681.         newHighScore = 
  682.         cc_QPS_propagateNetBackward(StartPattern,EndPattern,counter);
  683.         cc_QPS_updateNet(epsilon,mu,decay);
  684.         cc_initActivationArrays(); 
  685.         if((maxNoOfCovarianceUpdateCycles--) == 0) {
  686.         return;
  687.         }
  688.     }
  689.     } while(fabs(newHighScore-oldHighScore) >= 
  690.         (minCovarianceChange * oldHighScore));
  691. }
  692.  
  693.  
  694.  
  695. /*****************************************************************************
  696.   FUNCTION : cc_QPS_propagateNetBackward
  697.  
  698.   PURPOSE  : Calculate the special unit with the maximum covariance 
  699.   NOTES    :
  700.  
  701.   UPDATE   : 5.2.93
  702. ******************************************************************************/
  703. static float cc_QPS_propagateNetBackward(int StartPattern, int EndPattern, 
  704.                      int counter)
  705. {
  706.     float change=0.0,bestSpecialUnitScore,actPrime;
  707.     int s,o,p,n,h;
  708.     int start, end;
  709.     struct Unit *SpecialUnitPtr,*OutputUnitPtr,*hiddenUnitPtr;
  710.     struct Link *LinkPtr;
  711.  
  712.  
  713.     bestSpecialUnitScore = 
  714.     cc_calculateCorrelation(StartPattern,EndPattern,counter); 
  715.  
  716.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  717.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  718.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  719.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  720.     n = end - start + 1;
  721.     for(p=start; p<=end;p++){
  722.  
  723.     cc_initInputUnitsWithPattern(p);
  724.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,h) {
  725.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func) (hiddenUnitPtr);
  726.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  727.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  728.         }else{
  729.         hiddenUnitPtr->Out.output = 
  730.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  731.         }
  732.     }
  733.     
  734.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s) {
  735.         change = 0.0;
  736.         SpecialUnitPtr->act = SpecialUnitAct[p][s];
  737.         actPrime = (*SpecialUnitPtr->act_deriv_func)(SpecialUnitPtr);
  738.         FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  739.         change -= CorBetweenSpecialActAndOutError[s][o] * actPrime *  
  740.            ((OutputUnitError[p][o]-OutputUnitSumError[o]/n)/SumSqError);
  741.         }
  742.  
  743.         BIAS_CURRENT_SLOPE(SpecialUnitPtr) += change;     
  744.         FOR_ALL_LINKS(SpecialUnitPtr,LinkPtr) {
  745.         LN_CURRENT_SLOPE(LinkPtr) += change * LinkPtr->to->Out.output;
  746.         }
  747.     }
  748.     }
  749.     return(bestSpecialUnitScore);
  750. }
  751.  
  752.  
  753.  
  754. /*****************************************************************************
  755.   FUNCTION : cc_QPS_updateNet
  756.  
  757.   PURPOSE  : Update the weights of the special units with quickprop.
  758.   NOTES    :
  759.  
  760.   UPDATE   : 5.2.93
  761. ******************************************************************************/
  762. static void cc_QPS_updateNet(float epsilon, float mu, float decay)
  763. {
  764.     struct Unit *SpecialUnitPtr;
  765.     struct Link *LinkPtr;
  766.     float shrinkFactor=mu/(mu+1);
  767.     float bias_previousSlope,bias_currentSlope,bias_lastWeightChange,
  768.           bias_weightChange;
  769.     float ln_previousSlope,ln_currentSlope,ln_lastWeightChange,ln_weightChange;
  770.     int o;
  771.  
  772.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,o) {
  773.     bias_previousSlope = BIAS_PREVIOUS_SLOPE(SpecialUnitPtr);
  774.     bias_currentSlope = BIAS_CURRENT_SLOPE(SpecialUnitPtr) + 
  775.                         decay * SpecialUnitPtr->bias;
  776.     bias_lastWeightChange = BIAS_LAST_WEIGHT_CHANGE(SpecialUnitPtr);
  777.  
  778.     bias_weightChange = 0.0;
  779.  
  780.     if(bias_previousSlope > 0.0) {
  781.         if(bias_currentSlope > 0.0) {
  782.         bias_weightChange -= epsilon * bias_currentSlope;
  783.         }
  784.         if(bias_currentSlope >= (shrinkFactor * bias_previousSlope)) {
  785.         bias_weightChange += mu * bias_lastWeightChange;
  786.         }else {
  787.         bias_weightChange += (bias_lastWeightChange*bias_currentSlope)/ 
  788.             (bias_previousSlope - bias_currentSlope); 
  789.         }
  790.     }else if(bias_previousSlope < 0.0) {
  791.         if(bias_currentSlope < 0.0) {
  792.         bias_weightChange -= epsilon * bias_currentSlope;
  793.         }
  794.         if(bias_currentSlope <= (shrinkFactor * bias_previousSlope)) {
  795.         bias_weightChange += mu * bias_lastWeightChange;
  796.         }else {
  797.         bias_weightChange += (bias_lastWeightChange*bias_currentSlope)/ 
  798.             (bias_previousSlope - bias_currentSlope); 
  799.         }
  800.     }else{
  801.         bias_weightChange -= epsilon * bias_currentSlope;
  802.     }
  803.     SpecialUnitPtr->bias += 
  804.         (BIAS_LAST_WEIGHT_CHANGE(SpecialUnitPtr) = bias_weightChange); 
  805.     BIAS_PREVIOUS_SLOPE(SpecialUnitPtr) = bias_currentSlope;
  806.     BIAS_CURRENT_SLOPE(SpecialUnitPtr) = 0.0;
  807.  
  808.     FOR_ALL_LINKS(SpecialUnitPtr,LinkPtr) {
  809.    
  810.         ln_weightChange = 0.0;
  811.         ln_previousSlope = LN_PREVIOUS_SLOPE(LinkPtr);
  812.         ln_currentSlope = LN_CURRENT_SLOPE(LinkPtr) + decay*LinkPtr->weight;
  813.         ln_lastWeightChange = LN_LAST_WEIGHT_CHANGE(LinkPtr);
  814.    
  815.         if(ln_previousSlope > 0.0) {
  816.         if(ln_currentSlope > 0.0) {
  817.             ln_weightChange -= epsilon * ln_currentSlope;
  818.         }
  819.         if(ln_currentSlope >= (shrinkFactor * ln_previousSlope)) {
  820.             ln_weightChange += mu * ln_lastWeightChange;
  821.         }else{
  822.             ln_weightChange += (ln_lastWeightChange * ln_currentSlope) / 
  823.             (ln_previousSlope - ln_currentSlope); 
  824.         }
  825.         }else if(ln_previousSlope < 0.0) {
  826.         if(ln_currentSlope < 0.0) {
  827.             ln_weightChange -= epsilon * ln_currentSlope;
  828.         }
  829.         if(ln_currentSlope <= (shrinkFactor * ln_previousSlope)) {
  830.             ln_weightChange += mu * ln_lastWeightChange;
  831.         }else{
  832.             ln_weightChange += (ln_lastWeightChange * ln_currentSlope) / 
  833.             (ln_previousSlope - ln_currentSlope); 
  834.         }
  835.         }else{
  836.         ln_weightChange -= epsilon * ln_currentSlope;
  837.         }
  838.    
  839.         LinkPtr->weight += LN_LAST_WEIGHT_CHANGE(LinkPtr) = ln_weightChange; 
  840.         LN_PREVIOUS_SLOPE(LinkPtr)   = ln_currentSlope;
  841.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  842.     }
  843.     } 
  844. }
  845.  
  846.  
  847. /******************* end quickprop routines *************************/
  848.  
  849. /************* begin rprop routines *********************/
  850.  
  851.  
  852. /*****************************************************************************
  853.   FUNCTION : cc_RPO_trainNet
  854.  
  855.   PURPOSE  : Minimize the error of the output units.
  856.   NOTES    :
  857.  
  858.   UPDATE   : 5.2.93
  859. ******************************************************************************/
  860. static void cc_RPO_trainNet(int maxNoOfErrorUpdateCycles, float minErrorChange,
  861.                             int outPatience, int StartPattern, int EndPattern,
  862.                 float epsilonMinus, float epsilonPlus, float dummy,
  863.                 float **ParameterOutArray,int *NoOfOutParams)
  864. {
  865.     int m,p,sub,pat,counter=0;
  866.     int start, end;
  867.     float oldNetError;
  868.     static float OutParameter[1];
  869.  
  870.     *NoOfOutParams = 1;
  871.     *ParameterOutArray = OutParameter;
  872.  
  873.  
  874.     SumSqError = 0.0;
  875.     cc_initOutputUnits();
  876.  
  877.     /* compute the necessary sub patterns */
  878.  
  879.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  880.     if(KernelErrorCode != KRERR_NO_ERROR)
  881.         return;
  882.  
  883.     /* give oldNetError a meaningful initial value */
  884.     NET_ERROR(OutParameter)=FLOAT_MAX;
  885.     do {
  886.     oldNetError = NET_ERROR(OutParameter);
  887.     for(m=0;m<outPatience;m++) {
  888.         NET_ERROR(OutParameter) = 0.0;
  889.         SumSqError = 0.0;
  890.         KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  891.         start = kr_AbsPosOfFirstSubPat(StartPattern);
  892.         end   = kr_AbsPosOfFirstSubPat(EndPattern);
  893.         end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  894.         for(p=start; p<=end;p++){
  895.         kr_getSubPatternByNo(&pat,&sub,p);
  896.         cc_propagateNetForward(pat,sub);
  897.         NET_ERROR(OutParameter) += cc_RPO_propagateNetBackward(pat,sub);
  898.         }
  899.         cc_RPO_updateNet(epsilonMinus,epsilonPlus,dummy);
  900.         if(cc_printOnOff) {
  901.         printf("Epoch: %d NetError: %f \n",++counter,
  902.                NET_ERROR(OutParameter));
  903.         } 
  904.         if((maxNoOfErrorUpdateCycles--) == 0) {
  905.         return;
  906.         }
  907.     }
  908.     } while(fabs(oldNetError-NET_ERROR(OutParameter)) >= 
  909.         (minErrorChange * oldNetError));
  910. }
  911.  
  912.  
  913.  
  914. /*****************************************************************************
  915.   FUNCTION : cc_RPO_propagateNetBackward
  916.  
  917.   PURPOSE  : Propagate a pattern backward through the net.
  918.   NOTES    :
  919.  
  920.   UPDATE   : 5.2.93
  921. ******************************************************************************/
  922. static  float cc_RPO_propagateNetBackward(int PatternNo, int sub_pat_no)
  923. {
  924.     struct Link   *LinkPtr;
  925.     struct Site   *site_ptr;
  926.     struct Unit   *OutputUnitPtr;
  927.     Patterns      out_pat;
  928.     float         error,sum_error,devit;
  929.     int           dummy;
  930.  
  931.     sum_error = 0.0;    
  932.     out_pat = kr_getSubPatData(PatternNo,sub_pat_no,OUTPUT,NULL);
  933.  
  934.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
  935.     devit =  OutputUnitPtr->Out.output - *(out_pat++);
  936.  
  937.     sum_error += devit * devit;
  938.     error = devit * ((*OutputUnitPtr->act_deriv_func)(OutputUnitPtr) + 0.1);
  939.     SumSqError += error * error;
  940.  
  941.     BIAS_CURRENT_SLOPE(OutputUnitPtr) += error;
  942.  
  943.     if (UNIT_HAS_DIRECT_INPUTS(OutputUnitPtr)) {  
  944.         FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  945.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  946.         }
  947.     }else{
  948.         FOR_ALL_SITES_AND_LINKS(OutputUnitPtr,site_ptr,LinkPtr) {
  949.         LN_CURRENT_SLOPE(LinkPtr) += error * LinkPtr->to->Out.output;
  950.         }
  951.     }
  952.     }
  953.     return(sum_error); 
  954. }
  955.  
  956.  
  957.  
  958. /*****************************************************************************
  959.   FUNCTION : cc_RPO_updateNet
  960.  
  961.   PURPOSE  : Update the weights of the output units with rprop.
  962.   NOTES    :
  963.  
  964.   UPDATE   : 5.2.93
  965. ******************************************************************************/
  966. static void cc_RPO_updateNet(float epsilonMinus, float epsilonPlus, float dummy)
  967. {
  968.     struct Unit *OutputUnitPtr;
  969.     struct Link *LinkPtr;
  970.     float bias_previousSlope,bias_currentSlope,bias_lastWeightChange,
  971.           bias_weightChange=0.0;
  972.     float ln_previousSlope,ln_currentSlope,ln_lastWeightChange,
  973.           ln_weightChange=0.0;
  974.     int o;
  975.  
  976.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  977.     bias_previousSlope    = BIAS_PREVIOUS_SLOPE(OutputUnitPtr);
  978.     bias_currentSlope     = BIAS_CURRENT_SLOPE(OutputUnitPtr);
  979.     bias_lastWeightChange = 
  980.         (BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr) == 0.0) ? 
  981.         (1.0) : (BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr));
  982.       
  983.     if(bias_currentSlope != 0.0) {
  984.         if(bias_previousSlope == 0.0) {
  985.         bias_weightChange = 
  986.             fabs(bias_lastWeightChange) * SIGN(bias_currentSlope);
  987.         }else if(bias_previousSlope > 0.0) {  
  988.         if(bias_currentSlope > 0.0) {
  989.             bias_weightChange = epsilonPlus * bias_lastWeightChange;  
  990.         }else if(bias_currentSlope < 0.0) {
  991.             bias_weightChange = -epsilonMinus * bias_lastWeightChange;
  992.         }
  993.         }else if(bias_previousSlope < 0.0) {
  994.         if(bias_currentSlope < 0.0) {
  995.             bias_weightChange = epsilonPlus * bias_lastWeightChange;
  996.         }else if(bias_currentSlope > 0.0) {
  997.             bias_weightChange = -epsilonMinus * bias_lastWeightChange;
  998.         }
  999.         }else{
  1000.         bias_weightChange = 1.0 * SIGN(bias_currentSlope);
  1001.         }
  1002.  
  1003.         if(fabs(bias_weightChange) < 0.00001) {
  1004.         bias_weightChange = 0.00001 * SIGN(bias_weightChange);
  1005.         }
  1006.         if(fabs(bias_weightChange) > 10.0) {
  1007.         bias_weightChange = 10.0 * SIGN(bias_weightChange);
  1008.         }
  1009.  
  1010.         OutputUnitPtr->bias -= 
  1011.         (BIAS_LAST_WEIGHT_CHANGE(OutputUnitPtr) = bias_weightChange); 
  1012.         BIAS_PREVIOUS_SLOPE(OutputUnitPtr) = bias_currentSlope;
  1013.         BIAS_CURRENT_SLOPE(OutputUnitPtr) = 0.0;
  1014.     }
  1015.  
  1016.     FOR_ALL_LINKS(OutputUnitPtr,LinkPtr) {
  1017.    
  1018.         ln_previousSlope    = LN_PREVIOUS_SLOPE(LinkPtr);
  1019.         ln_currentSlope     = LN_CURRENT_SLOPE(LinkPtr);
  1020.         ln_lastWeightChange = 
  1021.         (LN_LAST_WEIGHT_CHANGE(LinkPtr) == 0.0) ? 
  1022.             (1.0) : (LN_LAST_WEIGHT_CHANGE(LinkPtr));
  1023.  
  1024.         if(ln_currentSlope != 0.0) {
  1025.         if(ln_previousSlope == 0.0) {
  1026.             ln_weightChange = 
  1027.             fabs(ln_lastWeightChange) * SIGN(ln_currentSlope);
  1028.         }else if(ln_previousSlope > 0.0) {  
  1029.             if(ln_currentSlope > 0.0) {
  1030.             ln_weightChange = epsilonPlus * ln_lastWeightChange;  
  1031.             }else if(ln_currentSlope < 0.0) {
  1032.             ln_weightChange = -epsilonMinus * ln_lastWeightChange;
  1033.             }
  1034.         }else if(ln_previousSlope < 0.0) {
  1035.             if(ln_currentSlope < 0.0) {
  1036.             ln_weightChange = epsilonPlus * ln_lastWeightChange;
  1037.             }else if(ln_currentSlope > 0.0) {
  1038.             ln_weightChange = -epsilonMinus * ln_lastWeightChange;
  1039.             }
  1040.         }else {
  1041.             ln_weightChange = 1.0 * SIGN(ln_currentSlope);
  1042.         }
  1043.     
  1044.         if(fabs(ln_weightChange) < 0.00001) {
  1045.             ln_weightChange = 0.00001 * SIGN(ln_weightChange);
  1046.         }
  1047.         if(fabs(ln_weightChange) > 10) {
  1048.             ln_weightChange = 10 * SIGN(ln_weightChange);
  1049.         }
  1050.  
  1051.         LinkPtr->weight -= 
  1052.             LN_LAST_WEIGHT_CHANGE(LinkPtr) = ln_weightChange; 
  1053.         LN_PREVIOUS_SLOPE(LinkPtr)   = ln_currentSlope;
  1054.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  1055.         }
  1056.     }
  1057.     }
  1058. }
  1059.  
  1060.  
  1061.  
  1062. /*****************************************************************************
  1063.   FUNCTION : cc_RPS_trainNet
  1064.  
  1065.   PURPOSE  : Maximize the covariance of the special units.
  1066.   NOTES    :
  1067.  
  1068.   UPDATE   : 5.2.93
  1069. ******************************************************************************/
  1070. static void cc_RPS_trainNet(int maxNoOfCovarianceUpdateCycles, 
  1071.                 float minCovarianceChange,
  1072.                             int specialPatience, int StartPattern, 
  1073.                 int EndPattern, float epsilonMinus,
  1074.                             float epsilonPlus, float dummy, 
  1075.                 int MaxSpecialUnitNo)
  1076. {
  1077.     int m,counter=0;
  1078.     float oldHighScore,newHighScore=0.0;
  1079.  
  1080.     cc_initErrorArrays();
  1081.     cc_calculateOutputUnitError(StartPattern,EndPattern);
  1082.  
  1083.     do {
  1084.     oldHighScore = newHighScore;
  1085.     for(m=0;m<specialPatience;m++) { 
  1086.         counter++;
  1087.         cc_calculateSpecialUnitActivation(StartPattern,EndPattern);
  1088.         newHighScore = 
  1089.         cc_RPS_propagateNetBackward(StartPattern,EndPattern,counter);
  1090.         cc_RPS_updateNet(epsilonMinus,epsilonPlus,dummy);
  1091.         cc_initActivationArrays(); 
  1092.         if((maxNoOfCovarianceUpdateCycles--) == 0) {
  1093.         return;
  1094.         }
  1095.     }
  1096.     } while(fabs(newHighScore-oldHighScore) >= 
  1097.         (minCovarianceChange * oldHighScore));
  1098. }
  1099.  
  1100.  
  1101.  
  1102. /*****************************************************************************
  1103.   FUNCTION : cc_RPS_propagateNetBackward
  1104.  
  1105.   PURPOSE  : Calculate the special unit with the maximum covariance and
  1106.              return it.
  1107.   NOTES    :
  1108.  
  1109.   UPDATE   : 5.2.93
  1110. ******************************************************************************/
  1111. static float cc_RPS_propagateNetBackward(int StartPattern, int EndPattern, 
  1112.                      int counter)
  1113. {
  1114.     float change=0.0,bestSpecialUnitScore,actPrime;
  1115.     int s,o,p,n,h;
  1116.     struct Unit *SpecialUnitPtr,*OutputUnitPtr,*hiddenUnitPtr;
  1117.     struct Link *LinkPtr;
  1118.     int start, end;
  1119.  
  1120.  
  1121.     bestSpecialUnitScore = 
  1122.     cc_calculateCorrelation(StartPattern,EndPattern,counter); 
  1123.  
  1124.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  1125.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  1126.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  1127.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  1128.     n = end - start + 1;
  1129.     for(p=start; p<=end;p++){
  1130.  
  1131.     cc_initInputUnitsWithPattern(p);
  1132.     FOR_ALL_HIDDEN_UNITS(hiddenUnitPtr,h) {
  1133.         hiddenUnitPtr->act = (*hiddenUnitPtr->act_func) (hiddenUnitPtr);
  1134.         if(hiddenUnitPtr->out_func == OUT_IDENTITY) {
  1135.         hiddenUnitPtr->Out.output = hiddenUnitPtr->act;
  1136.         }else {
  1137.         hiddenUnitPtr->Out.output = 
  1138.             (*hiddenUnitPtr->out_func) (hiddenUnitPtr->act);
  1139.         }
  1140.     }
  1141.     
  1142.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s) {
  1143.         change = 0.0;
  1144.         SpecialUnitPtr->act = SpecialUnitAct[p][s];
  1145.         actPrime = (*SpecialUnitPtr->act_deriv_func)(SpecialUnitPtr);
  1146.         FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,o) {
  1147.         change -= CorBetweenSpecialActAndOutError[s][o] * actPrime *  
  1148.            ((OutputUnitError[p][o]-OutputUnitSumError[o]/n)/SumSqError);
  1149.         }
  1150.  
  1151.         BIAS_CURRENT_SLOPE(SpecialUnitPtr) += change;     
  1152.         FOR_ALL_LINKS(SpecialUnitPtr,LinkPtr) {
  1153.         LN_CURRENT_SLOPE(LinkPtr) += change * LinkPtr->to->Out.output;
  1154.         }
  1155.     }
  1156.     }
  1157.     return(bestSpecialUnitScore);
  1158. }
  1159.  
  1160.  
  1161.  
  1162. /*****************************************************************************
  1163.   FUNCTION : cc_RPS_updateNet
  1164.  
  1165.   PURPOSE  : Update the weights of the special units.
  1166.   NOTES    :
  1167.  
  1168.   UPDATE   : 5.2.93
  1169. ******************************************************************************/
  1170. static void cc_RPS_updateNet(float epsilonMinus, float epsilonPlus, float dummy)
  1171. {
  1172.     struct Unit *specialUnitPtr;
  1173.     struct Link *LinkPtr;
  1174.     float bias_previousSlope,bias_currentSlope,bias_lastWeightChange,
  1175.           bias_weightChange=0.0;
  1176.     float ln_previousSlope,ln_currentSlope,ln_lastWeightChange,
  1177.           ln_weightChange=0.0;
  1178.     int s;
  1179.  
  1180.     FOR_ALL_SPECIAL_UNITS(specialUnitPtr,s) {
  1181.     bias_previousSlope    = BIAS_PREVIOUS_SLOPE(specialUnitPtr);
  1182.     bias_currentSlope     = BIAS_CURRENT_SLOPE(specialUnitPtr);
  1183.     bias_lastWeightChange = 
  1184.         (BIAS_LAST_WEIGHT_CHANGE(specialUnitPtr) == 0.0) ? 
  1185.         (1.0) : (BIAS_LAST_WEIGHT_CHANGE(specialUnitPtr));
  1186.    
  1187.     if(bias_currentSlope != 0.0) {
  1188.         if(bias_previousSlope == 0.0) {
  1189.         bias_weightChange = 
  1190.             fabs(bias_lastWeightChange) * SIGN(bias_currentSlope);
  1191.         }else if(bias_previousSlope > 0.0) {  
  1192.         if(bias_currentSlope > 0.0) {
  1193.             bias_weightChange = epsilonPlus * bias_lastWeightChange;  
  1194.         }else if(bias_currentSlope < 0.0) {
  1195.             bias_weightChange = -epsilonMinus * bias_lastWeightChange;
  1196.         }
  1197.         }else if(bias_previousSlope < 0.0) {
  1198.         if(bias_currentSlope < 0.0) {
  1199.             bias_weightChange = epsilonPlus * bias_lastWeightChange;
  1200.         }else if(bias_currentSlope > 0.0) {
  1201.             bias_weightChange = -epsilonMinus * bias_lastWeightChange;
  1202.         }
  1203.         }else {
  1204.         bias_weightChange = 1.0 * SIGN(bias_currentSlope);
  1205.         }
  1206.  
  1207.         if(fabs(bias_weightChange) < 0.00001) {
  1208.         bias_weightChange = 0.00001 * SIGN(bias_weightChange);
  1209.         }
  1210.         if(fabs(bias_weightChange) > 10.0) {
  1211.         bias_weightChange = 10.0 * SIGN(bias_weightChange);
  1212.         }
  1213.   
  1214.         specialUnitPtr->bias -= 
  1215.         (BIAS_LAST_WEIGHT_CHANGE(specialUnitPtr) = bias_weightChange); 
  1216.         BIAS_PREVIOUS_SLOPE(specialUnitPtr) = bias_currentSlope;
  1217.         BIAS_CURRENT_SLOPE(specialUnitPtr) = 0.0;
  1218.     }
  1219.  
  1220.     FOR_ALL_LINKS(specialUnitPtr,LinkPtr) {
  1221.    
  1222.         ln_previousSlope    = LN_PREVIOUS_SLOPE(LinkPtr);
  1223.         ln_currentSlope     = LN_CURRENT_SLOPE(LinkPtr);
  1224.         ln_lastWeightChange = 
  1225.         (LN_LAST_WEIGHT_CHANGE(LinkPtr) == 0.0) ? 
  1226.             (1.0) : (LN_LAST_WEIGHT_CHANGE(LinkPtr));
  1227.  
  1228.         if(ln_currentSlope != 0.0) {
  1229.         if(ln_previousSlope == 0.0) {
  1230.             ln_weightChange = 
  1231.             fabs(ln_lastWeightChange) * SIGN(ln_currentSlope);
  1232.         }else if(ln_previousSlope > 0.0) {  
  1233.             if(ln_currentSlope > 0.0) {
  1234.             ln_weightChange = epsilonPlus * ln_lastWeightChange;  
  1235.             }else if(ln_currentSlope < 0.0) {
  1236.             ln_weightChange = -epsilonMinus * ln_lastWeightChange;
  1237.             }
  1238.         }else if(ln_previousSlope < 0.0) {
  1239.             if(ln_currentSlope < 0.0) {
  1240.             ln_weightChange = epsilonPlus * ln_lastWeightChange;
  1241.             }else if(ln_currentSlope > 0.0) {
  1242.             ln_weightChange = -epsilonMinus * ln_lastWeightChange;
  1243.             }
  1244.         }else {
  1245.             ln_weightChange = 1.0 * SIGN(ln_currentSlope);
  1246.         }
  1247.     
  1248.         if(fabs(ln_weightChange) < 0.00001) {
  1249.             ln_weightChange = 0.00001 * SIGN(ln_weightChange);
  1250.         }
  1251.         if(fabs(ln_weightChange) > 10) {
  1252.             ln_weightChange = 10 * SIGN(ln_weightChange);
  1253.         }
  1254.  
  1255.         LinkPtr->weight -= 
  1256.             LN_LAST_WEIGHT_CHANGE(LinkPtr) = ln_weightChange; 
  1257.         LN_PREVIOUS_SLOPE(LinkPtr)   = ln_currentSlope;
  1258.         LN_CURRENT_SLOPE(LinkPtr)    = 0.0;
  1259.         }
  1260.     }
  1261.     }
  1262. }
  1263.  
  1264. /******************* end rprop routines *************************/
  1265.  
  1266.  
  1267.  
  1268. /*****************************************************************************
  1269.   FUNCTION : LEARN_CasCor
  1270.  
  1271.   PURPOSE  : The main learn routine of CC
  1272.   NOTES    :
  1273.  
  1274.   UPDATE   : 5.2.93
  1275. ******************************************************************************/
  1276. krui_err LEARN_CasCor(int StartPattern, int EndPattern,
  1277.                       float *ParameterInArray, int NoOfInParams,
  1278.                       float **ParameterOutArray, int *NoOfOutParams)
  1279.     
  1280. {
  1281.     static int   OldMaxSpecialUnitNo=0,MaxSpecialUnitNo;
  1282.     static int   maxNoOfErrorUpdateCycles,maxNoOfCovarianceUpdateCycles,
  1283.                  outPatience,specialPatience;
  1284.     static int   maxYPosOfHiddenUnit,xPosOfLastInsertedHiddenUnit,
  1285.                  yPosOfLastInsertedHiddenUnit;
  1286.     static int   specialFuncType,oldSpecialFuncType,outputXMax,learnFunc;
  1287.     static float maxPixelError,minErrorChange,minCovarianceChange,
  1288.                  param1,param2,param3,param4,param5,param6;
  1289.   
  1290.     srand48((long)time((long *)0)); 
  1291.   
  1292.     /* Enter this path only  if "all-button" in the remote pannel was pressed */
  1293.     if(cc_allButtonIsPressed == 1) { 
  1294.     
  1295.     param1 = ParameterInArray[0];
  1296.     param2 = ParameterInArray[1];
  1297.     param3 = ParameterInArray[2];
  1298.     
  1299.     param4 = ParameterInArray[3];
  1300.     param5 = ParameterInArray[4];
  1301.     param6 = 0.0001;
  1302.     
  1303.     maxPixelError = ParameterInArray[6]; /* cc_data.GLOBAL.pixelError */
  1304.     learnFunc = (int)ParameterInArray[7]; /* cc_data.GLOBAL.learningFunc */
  1305.     cc_printOnOff = (int)ParameterInArray[8]; /* cc_data.GLOBAL.onOff */ 
  1306.  
  1307.     /* cc_data.CAND.covarianceChange */
  1308.     minCovarianceChange = ParameterInArray[9]; 
  1309.  
  1310.     /* cc_data.CAND.candidatePatience */
  1311.     specialPatience = ParameterInArray[10]; 
  1312.  
  1313.     /* cc_data.CAND.maxNoOfUpdateCycles */
  1314.     maxNoOfCovarianceUpdateCycles = ParameterInArray[11]; 
  1315.  
  1316.     /* cc_data.CAND.maxNoOfCandUnits */
  1317.     MaxSpecialUnitNo = ParameterInArray[12]; 
  1318.  
  1319.     /* cc_data.CAND.actFunc */
  1320.     specialFuncType = (int)ParameterInArray[13]; 
  1321.     
  1322.     /* cc_data.OUT.errorChange */
  1323.     minErrorChange  = ParameterInArray[14];
  1324.  
  1325.     /* cc_data.OUT.outputPatience */ 
  1326.     outPatience  = ParameterInArray[15]; 
  1327.  
  1328.     /* cc_data.OUT.maxNoOfUpdateCycles */
  1329.     maxNoOfErrorUpdateCycles = ParameterInArray[16]; 
  1330.     
  1331.     cc_compareActFunctions(specialFuncType,CC);
  1332.     
  1333.     cc_end = 0;
  1334.     cc_cascade = 1;
  1335.     
  1336.     switch(learnFunc) {
  1337.       case BACKPROP:
  1338.         cc_trainOutputUnits  = cc_BPO_trainNet;
  1339.         cc_trainSpecialUnits = cc_BPS_trainNet;
  1340.         break;
  1341.       case QUICKPROP:
  1342.         cc_trainOutputUnits  = cc_QPO_trainNet;
  1343.         cc_trainSpecialUnits = cc_QPS_trainNet;
  1344.         break;
  1345.       case RPROP: 
  1346.         cc_trainOutputUnits  = cc_RPO_trainNet;
  1347.         cc_trainSpecialUnits = cc_RPS_trainNet;
  1348.         break;
  1349.       default: CC_ERROR(KRERR_CC_ERROR3);
  1350.     }
  1351.     
  1352.     maxYPosOfHiddenUnit = 
  1353.         xPosOfLastInsertedHiddenUnit =
  1354.         yPosOfLastInsertedHiddenUnit =
  1355.             outputXMax = 0;
  1356.     KernelErrorCode = 
  1357.         cc_calculateNetParameters(&maxYPosOfHiddenUnit,
  1358.                       &xPosOfLastInsertedHiddenUnit,
  1359.                       &yPosOfLastInsertedHiddenUnit,
  1360.                       &outputXMax);
  1361.     ERROR_CHECK;
  1362.     }
  1363.  
  1364.     if(cc_printOnOff){
  1365.     if(strcmp(krui_getUpdateFunc(),"CC_Order")){
  1366.         return(KRERR_CC_ERROR10);
  1367.     }
  1368.     if(strcmp(krui_getInitialisationFunc(),"CC_Weights")){
  1369.         return(KRERR_CC_ERROR11);
  1370.     }
  1371.     }
  1372.   
  1373.     if(cc_end){
  1374.     return(KRERR_NO_ERROR);
  1375.     }
  1376.   
  1377.     if(NetModified || (TopoSortID!=TOPOLOGICAL_CC) || 
  1378.        (LearnFuncHasChanged) || (OldMaxSpecialUnitNo!=MaxSpecialUnitNo) || 
  1379.        (cc_update)) {
  1380.     
  1381.     OldMaxSpecialUnitNo = MaxSpecialUnitNo;
  1382.     oldSpecialFuncType  = specialFuncType;
  1383.     
  1384.     KernelErrorCode = cc_deleteAllSpecialUnits();
  1385.     ERROR_CHECK; 
  1386.     
  1387.     KernelErrorCode = 
  1388.        cc_generateSpecialUnits(MaxSpecialUnitNo,outputXMax,specialFuncType);
  1389.     ERROR_CHECK;
  1390.     
  1391.     KernelErrorCode = kr_topoSort(TOPOLOGICAL_CC);
  1392.     ERROR_CHECK;    
  1393.     
  1394.     if(CC_TEST) {
  1395.         cc_printUnitArray();
  1396.         cc_printTopoPtrArray();
  1397.     }
  1398.     
  1399.     KernelErrorCode = cc_setPointers();
  1400.     ERROR_CHECK;
  1401.     
  1402.     cc_update = 0;
  1403.     LearnFuncHasChanged = 0;
  1404.     NetModified = 0;
  1405.     }
  1406.  
  1407.     if(cc_allButtonIsPressed == 1) {
  1408.     KernelErrorCode = cc_freeStorage(StartPattern,EndPattern,0);
  1409.     ERROR_CHECK;
  1410.     KernelErrorCode = 
  1411.         cc_allocateStorage(StartPattern,EndPattern,MaxSpecialUnitNo);
  1412.     ERROR_CHECK;
  1413.     }
  1414.  
  1415.     if(oldSpecialFuncType != specialFuncType){
  1416.     oldSpecialFuncType = specialFuncType;
  1417.     cc_changeActFuncOfSpecialUnits(specialFuncType,CC);
  1418.     }
  1419.   
  1420.     KernelErrorCode = cc_initSpecialUnitLinks();
  1421.     ERROR_CHECK;
  1422.   
  1423.     /* For safety, this error should only appear, if someone has changed 
  1424.        the program in a wrong way!!!
  1425.        */
  1426.     if(cc_storageFree){ 
  1427.     CC_ERROR(KRERR_CC_ERROR2);    
  1428.     }
  1429.     if(cc_allButtonIsPressed == 1) {
  1430.     cc_allButtonIsPressed = 0;
  1431.     if((outPatience != 0) && (maxNoOfErrorUpdateCycles != 0)) {
  1432.         (*cc_trainOutputUnits)(maxNoOfErrorUpdateCycles,minErrorChange,
  1433.                    outPatience,StartPattern,EndPattern,param1,
  1434.                    param2,param3,ParameterOutArray,
  1435.                    NoOfOutParams);
  1436.     }
  1437.     }
  1438.   
  1439.     if(cc_test(StartPattern,EndPattern,maxPixelError) ==  CONTINUE_LEARNING) {
  1440.     if((specialPatience != 0) && (maxNoOfCovarianceUpdateCycles != 0)) {
  1441.         (*cc_trainSpecialUnits)(maxNoOfCovarianceUpdateCycles,
  1442.                     minCovarianceChange,specialPatience,
  1443.                     StartPattern,EndPattern,param4,
  1444.                     param5,param6,MaxSpecialUnitNo);
  1445.     }
  1446.     }else {            /* STOP_LEARNING  */
  1447.     cc_end = 1;
  1448.     return(KRERR_NO_ERROR);
  1449.     }
  1450.   
  1451.     if((specialPatience != 0) && (maxNoOfCovarianceUpdateCycles != 0)) {
  1452.     KernelErrorCode = cc_generateHiddenUnit(maxYPosOfHiddenUnit,
  1453.                         &xPosOfLastInsertedHiddenUnit,
  1454.                         &yPosOfLastInsertedHiddenUnit);
  1455.     ERROR_CHECK;
  1456.     }
  1457.   
  1458.     if((outPatience != 0) && (maxNoOfErrorUpdateCycles != 0)) {
  1459.     (*cc_trainOutputUnits)(maxNoOfErrorUpdateCycles,minErrorChange,
  1460.                    outPatience,StartPattern,EndPattern,param1,
  1461.                    param2,param3,ParameterOutArray,NoOfOutParams); 
  1462.     }
  1463.     return(KRERR_NO_ERROR);
  1464. }
  1465.  
  1466.  
  1467.  
  1468. /*****************************************************************************
  1469.   FUNCTION : krui_err cc_generateHiddenUnit
  1470.  
  1471.   PURPOSE  : Generates a new hidden unit 
  1472.   NOTES    :
  1473.  
  1474.   UPDATE   : 5.2.93
  1475. ******************************************************************************/
  1476. static krui_err cc_generateHiddenUnit(int maxYPosOfHiddenUnit, 
  1477.                       int *xPosOfLastInsertedHiddenUnit,
  1478.                                       int *yPosOfLastInsertedHiddenUnit)
  1479. {
  1480.     int CurrentUnit,dummy,NewHiddenUnit,s;
  1481.     struct Unit *HiddenUnitPtr,*SpecialUnitPtr,*OutputUnitPtr;
  1482.  
  1483.     CurrentUnit = 
  1484.     KernelErrorCode = 
  1485.         kr_copyUnit(ONLY_INPUTS,GET_UNIT_NO(bestSpecialUnitPtr));
  1486.     if(KernelErrorCode < 0) {
  1487.     ERROR_CHECK;
  1488.     }
  1489.  
  1490.     KernelErrorCode = KRERR_NO_ERROR;
  1491.     KernelErrorCode = kr_unitSetTType(CurrentUnit,HIDDEN); 
  1492.     ERROR_CHECK;
  1493.  
  1494.     HiddenUnitPtr = kr_getUnitPtr(CurrentUnit); 
  1495.     ERROR_CHECK;
  1496.  
  1497.     KernelErrorCode = 
  1498.     cc_setHiddenUnit(HiddenUnitPtr,maxYPosOfHiddenUnit,
  1499.              xPosOfLastInsertedHiddenUnit,
  1500.              yPosOfLastInsertedHiddenUnit);
  1501.     ERROR_CHECK;
  1502.  
  1503.     KernelErrorCode = krui_setCurrentUnit(CurrentUnit); 
  1504.     ERROR_CHECK;
  1505.  
  1506.     NewHiddenUnit = CurrentUnit;
  1507.  
  1508.     /* generate links between output unit and new hidden unit */
  1509.     FOR_ALL_OUTPUT_UNITS(OutputUnitPtr,dummy){
  1510.     CurrentUnit = GET_UNIT_NO(OutputUnitPtr);
  1511.     KernelErrorCode = krui_setCurrentUnit(CurrentUnit); 
  1512.     ERROR_CHECK;
  1513.  
  1514.     KernelErrorCode = krui_createLink(NewHiddenUnit,0.0);
  1515.     ERROR_CHECK; 
  1516.     }
  1517.  
  1518.     FOR_ALL_SPECIAL_UNITS(SpecialUnitPtr,s){
  1519.     KernelErrorCode = krui_setCurrentUnit(GET_UNIT_NO(SpecialUnitPtr));
  1520.     ERROR_CHECK;
  1521.  
  1522.     krui_createLink(NewHiddenUnit,cc_generateRandomNo(CC_MAX_VALUE));
  1523.     }
  1524.  
  1525.     KernelErrorCode = kr_topoSort(TOPOLOGICAL_CC);
  1526.     ERROR_CHECK;    
  1527.  
  1528.     if(CC_TEST) {
  1529.     cc_printUnitArray();
  1530.     cc_printTopoPtrArray();
  1531.     }
  1532.  
  1533.     KernelErrorCode = cc_setPointers();
  1534.     ERROR_CHECK;
  1535.  
  1536.     NetModified = FALSE;
  1537.     return(KRERR_NO_ERROR);
  1538. }
  1539.  
  1540.  
  1541.  
  1542. /*****************************************************************************
  1543.   FUNCTION : cc_test
  1544.  
  1545.   PURPOSE  : Tests whether to continue learning or not.
  1546.   NOTES    :
  1547.  
  1548.   UPDATE   : 5.2.93
  1549. ******************************************************************************/
  1550. static int cc_test(int StartPattern, int EndPattern, float maxPixelError)
  1551. {
  1552.     int p,sub,pat,o;
  1553.     int start, end;
  1554.     Patterns out_pat;
  1555.     struct Unit *unitPtr;
  1556.  
  1557.     /* compute the necessary sub patterns */
  1558.  
  1559.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  1560.     if(KernelErrorCode != KRERR_NO_ERROR)
  1561.         return (KernelErrorCode);
  1562.  
  1563.     KernelErrorCode = kr_initSubPatternOrder(StartPattern,EndPattern);
  1564.     start = kr_AbsPosOfFirstSubPat(StartPattern);
  1565.     end   = kr_AbsPosOfFirstSubPat(EndPattern);
  1566.     end  += kr_NoOfSubPatPairs(EndPattern) - 1;
  1567.     for(p=start; p<=end;p++){
  1568.     kr_getSubPatternByNo(&pat,&sub,p);
  1569.     cc_propagateNetForward(pat,sub);
  1570.  
  1571.     out_pat = kr_getSubPatData(pat,sub,OUTPUT,NULL);
  1572.     FOR_ALL_OUTPUT_UNITS(unitPtr,o){
  1573.         if((fabs(*(out_pat++) - unitPtr->Out.output))>maxPixelError){
  1574.         return(CONTINUE_LEARNING);
  1575.         } 
  1576.     }
  1577.     }
  1578.     return(STOP_LEARNING);
  1579. }
  1580.  
  1581.  
  1582.  
  1583. /*****************************************************************************
  1584.   FUNCTION : cc_generateSpecialUnits
  1585.  
  1586.   PURPOSE  : Generates the special units
  1587.   NOTES    :
  1588.  
  1589.   UPDATE   : 5.2.93
  1590. ******************************************************************************/
  1591. static krui_err cc_generateSpecialUnits(int MaxSpecialUnitNo, int OutputXMax, 
  1592.                     int type)
  1593. {
  1594.     int i,selector;
  1595.     struct Unit *UnitPtr;
  1596.     int CurrentUnit;
  1597.  
  1598.     for(i=0;i<MaxSpecialUnitNo;i++) {
  1599.     if(type==RANDOM){
  1600.         selector = i % (NO_OF_ACT_FUNCS - 1);
  1601.     }else{
  1602.         selector = type;
  1603.     }
  1604.     KernelErrorCode = 
  1605.         kr_unitSetTType(CurrentUnit=kr_makeDefaultUnit(),SPECIAL); 
  1606.     ERROR_CHECK;
  1607.  
  1608.     KernelErrorCode = 
  1609.         krui_setUnitActFunc(CurrentUnit,cc_actFuncArray[selector]);
  1610.     ERROR_CHECK;  
  1611.  
  1612.     UnitPtr = kr_getUnitPtr(CurrentUnit); 
  1613.     ERROR_CHECK;
  1614.  
  1615.     SET_UNIT_XPOS(UnitPtr,OutputXMax+3);
  1616.     SET_UNIT_YPOS(UnitPtr,2+i);
  1617.     KernelErrorCode = krui_setCurrentUnit(CurrentUnit); 
  1618.     ERROR_CHECK;
  1619.  
  1620.     /* links between special units and input units */
  1621.     FOR_ALL_UNITS(UnitPtr){
  1622.         if((IS_INPUT_UNIT(UnitPtr) || IS_HIDDEN_UNIT(UnitPtr)) && 
  1623.            UNIT_IN_USE(UnitPtr)) {
  1624.         KernelErrorCode = 
  1625.             krui_createLink(GET_UNIT_NO(UnitPtr),
  1626.                     cc_generateRandomNo(CC_MAX_VALUE)); 
  1627.         ERROR_CHECK;
  1628.         }
  1629.     }
  1630.     }  
  1631.     return(KRERR_NO_ERROR);
  1632. }
  1633.